package bancosys.tec.security.impl.domain;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

import jmine.tec.persist.annotation.DiscriminatorComment;

import org.apache.commons.lang.builder.HashCodeBuilder;
import org.hibernate.util.EqualsHelper;

import bancosys.tec.component.Documentation;
import bancosys.tec.persist.authorization.annotation.DisplayName;
import bancosys.tec.security.authorization.AuthorizablePermission;
import bancosys.tec.security.authorization.Permission;

/**
 * Credencial que representa um item autorizável.
 * 
 * @author evaristo.goes
 */
@Entity
@DiscriminatorValue("5")
@DiscriminatorComment("AUTORIZACAO")
@DisplayName("Credencial para Tela de Autorização")
public class AuthorizableCredential extends Credential {

    // Número impar qualquer
    private static final int HASH_RANDOM_1 = 11;

    // Número impar qualquer diferente do primeiro
    private static final int HASH_RANDOM_2 = 41;

    private String authorizable;

    /**
     * Contrutor.
     */
    AuthorizableCredential() {
        // Não faz nada
    }

    /**
     * Contrutor.
     * 
     * @param authorizable Nome do item autorizável.
     */
    public AuthorizableCredential(String authorizable) {
        if (authorizable == null || "".equals(authorizable)) {
            throw new IllegalArgumentException("Autorizável deve ser informado.");
        }
        this.authorizable = authorizable;
    }

    /**
     * Retorna o nome do item autorizável que a credencial representa.
     * 
     * @return String Nome do item autorizável que a credencial representa
     */
    @Column(name = "AUTHORIZABLE")
    @Documentation("NOME DO AUTHORIZABLE QUE A CREDENCIAL REPRESENTA.")
    public String getAuthorizable() {
        return this.authorizable;
    }

    /**
     * Seta o nome do item autorizável que a credencial representa.
     * 
     * @param authorizable Nome do item autorizável que a credencial representa
     */
    public void setAuthorizable(String authorizable) {
        this.authorizable = authorizable;
    }

    /**
     * Compara esse objeto com o passado como parâmetro. Utiliza o nome do item autorizável como critério de comparação.
     * 
     * @param obj o outro objeto.
     * @return <code>true</code> se forem iguais, <code>false</code> caso contrário.
     */
    @Override
    public boolean equals(Object obj) {
        if (!super.equals(obj)) {
            return false;
        }

        if (!(obj instanceof AuthorizableCredential)) {
            return false;
        }
        AuthorizableCredential other = (AuthorizableCredential) obj;

        if (!EqualsHelper.equals(other.authorizable, this.authorizable)) {
            return false;
        }
        if (!EqualsHelper.equals(other.getClient(), this.getClient())) {
            return false;
        }
        return true;
    }

    /**
     * Devolve o hashCode.
     * 
     * @return o hashCode.
     */
    @Override
    public int hashCode() {
        int superHash = super.hashCode();
        HashCodeBuilder hashCodeBuilder = new HashCodeBuilder(HASH_RANDOM_1, HASH_RANDOM_2);
        hashCodeBuilder.appendSuper(superHash);
        hashCodeBuilder.append(this.getClient().getName());
        hashCodeBuilder.append(this.authorizable);
        return hashCodeBuilder.toHashCode();
    }

    /**
     * Devolve a representação desse objeto.
     * 
     * @return a representação desse objeto.
     */
    @Override
    public String toString() {
        return "AuthorizableCredential (" + this.authorizable + ")";
    }

    /**
     * @return cria uma {@link Permission}
     */
    @Override
    public Permission createPermission() {
        return new AuthorizablePermission(this.getAuthorizable());
    }
}